package com.jjty.dataGenerator.akq.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.jjty.dataGenerator.akq.entity.*;
import com.jjty.dataGenerator.akq.service.DataService;
import com.jjty.dataGenerator.akq.service.RequestLogService;
import com.jjty.dataGenerator.utils.IPUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

@RestController
@RequestMapping("/api")
public class BaseDataController {

    @Autowired
    private DataService dataService;
    @Autowired
    private RequestLogService requestLogService;

    @Autowired
    private ObjectMapper objectMapper;


    /*
     * 基础数据
     */
    @RequestMapping("/akq/baseData")
    public ResponseResult<Void> uploadData(@RequestBody String requestBody, HttpServletRequest request) {
        RequestLogEntity log = new RequestLogEntity();
        try {
            // 校验请求参数
            if (!validateRequestBody(requestBody, BaseDataEntity.class)) {
                String errorMessage = "请求参数包含非法字段: " + requestBody;
                log.setNotes(errorMessage);
                log.setRequestUrl("/api/akq/baseData");
                log.setRequestMethod("POST");
                log.setRequestBody(requestBody);
                log.setRequestTime(LocalDateTime.now());
                log.setSuccess(false);
                log.setIp(IPUtils.getClientIp(request));
                requestLogService.saveRequestLog(log); // 保存日志
                return ResponseResult.fail(errorMessage);
            }

            BaseDataEntity data = objectMapper.readValue(requestBody, BaseDataEntity.class);

            // 记录请求前的信息
            log.setRequestUrl("/api/akq/baseData");
            log.setRequestMethod("POST");
            log.setRequestBody(requestBody);
            log.setRequestTime(LocalDateTime.now());
            log.setIp(IPUtils.getClientIp(request));

            dataService.saveData(data);

            // 只有请求成功时才设置成功状态并保存日志
            log.setSuccess(true);
            requestLogService.saveRequestLog(log);

            return ResponseResult.success();
        } catch (Exception e) {
            // 记录请求失败信息
            log.setSuccess(false);
            log.setNotes("数据接收失败: " + e.getMessage());
            requestLogService.saveRequestLog(log);

            return ResponseResult.fail("数据接收失败: " + e.getMessage());
        }
    }

    /*
     * 心跳数据
     */
    @RequestMapping("/akq/heartbeatData")
    public ResponseResult<Void> uploadFunctionalData(@RequestBody String requestBody, HttpServletRequest request) {
        RequestLogEntity log = new RequestLogEntity();
        try {
            // 校验请求参数
            if (!validateRequestBody(requestBody, HeartbeatDataEntity.class)) {
                String errorMessage = "请求参数包含非法字段: " + requestBody;
                log.setNotes(errorMessage);
                log.setRequestUrl("/api/akq/heartbeatData");
                log.setRequestMethod("POST");
                log.setRequestBody(requestBody);
                log.setRequestTime(LocalDateTime.now());
                log.setSuccess(false);
                log.setIp(IPUtils.getClientIp(request));
                requestLogService.saveRequestLog(log); // 保存日志
                return ResponseResult.fail(errorMessage);
            }

            HeartbeatDataEntity data = objectMapper.readValue(requestBody, HeartbeatDataEntity.class);

            // 记录请求前的信息
            log.setRequestUrl("/api/akq/heartbeatData");
            log.setRequestMethod("POST");
            log.setRequestBody(requestBody);
            log.setRequestTime(LocalDateTime.now());
            log.setIp(IPUtils.getClientIp(request));

            dataService.saveFunctionalData(data);

            // 只有请求成功时才设置成功状态并保存日志
            log.setSuccess(true);
            requestLogService.saveRequestLog(log);

            return ResponseResult.success();
        } catch (Exception e) {
            // 记录请求失败信息
            log.setSuccess(false);
            log.setNotes("数据接收失败: " + e.getMessage());
            requestLogService.saveRequestLog(log);

            return ResponseResult.fail("数据接收失败: " + e.getMessage());
        }
    }

    /*
     * 设备数据
     */
    @RequestMapping("/akq/deviceData")
    public ResponseResult<Void> uploadDeviceData(@RequestBody String requestBody, HttpServletRequest request) {
        RequestLogEntity log = new RequestLogEntity();
        try {
            // 校验请求参数
            if (!validateRequestBody(requestBody, DeviceDataEntity.class)) {
                String errorMessage = "请求参数包含非法字段: " + requestBody;
                log.setNotes(errorMessage);
                log.setRequestUrl("/api/akq/deviceData");
                log.setRequestMethod("POST");
                log.setRequestBody(requestBody);
                log.setRequestTime(LocalDateTime.now());
                log.setSuccess(false);
                log.setIp(IPUtils.getClientIp(request));
                requestLogService.saveRequestLog(log); // 保存日志
                return ResponseResult.fail(errorMessage);
            }

            DeviceDataEntity data = objectMapper.readValue(requestBody, DeviceDataEntity.class);

            // 记录请求前的信息
            log.setRequestUrl("/api/akq/deviceData");
            log.setRequestMethod("POST");
            log.setRequestBody(requestBody);
            log.setRequestTime(LocalDateTime.now());
            log.setIp(IPUtils.getClientIp(request));

            dataService.saveDeviceData(data);

            // 只有请求成功时才设置成功状态并保存日志
            log.setSuccess(true);
            requestLogService.saveRequestLog(log);

            return ResponseResult.success();
        } catch (Exception e) {
            // 记录请求失败信息
            log.setSuccess(false);
            log.setNotes("数据接收失败: " + e.getMessage());
            requestLogService.saveRequestLog(log);

            return ResponseResult.fail("数据接收失败: " + e.getMessage());
        }
    }

    /*
     * 通话数据
     */
    @RequestMapping("/akq/callInfoData")
    public ResponseResult<Void> uploadCallInfoData(@RequestBody String requestBody, HttpServletRequest request) {
        RequestLogEntity log = new RequestLogEntity();
        try {
            // 校验请求参数
            if (!validateRequestBody(requestBody, CallInfoDataEntity.class)) {
                String errorMessage = "请求参数包含非法字段: " + requestBody;
                log.setNotes(errorMessage);
                log.setRequestUrl("/api/akq/callInfoData");
                log.setRequestMethod("POST");
                log.setRequestBody(requestBody);
                log.setRequestTime(LocalDateTime.now());
                log.setSuccess(false);
                log.setIp(IPUtils.getClientIp(request));
                requestLogService.saveRequestLog(log); // 保存日志
                return ResponseResult.fail(errorMessage);
            }

            CallInfoDataEntity data = objectMapper.readValue(requestBody, CallInfoDataEntity.class);

            // 记录请求前的信息
            log.setRequestUrl("/api/akq/callInfoData");
            log.setRequestMethod("POST");
            log.setRequestBody(requestBody);
            log.setRequestTime(LocalDateTime.now());
            log.setIp(IPUtils.getClientIp(request));

            dataService.saveCallInfoData(data);

            // 只有请求成功时才设置成功状态并保存日志
            log.setSuccess(true);
            requestLogService.saveRequestLog(log);

            return ResponseResult.success();
        } catch (Exception e) {
            // 记录请求失败信息
            log.setSuccess(false);
            log.setNotes("数据接收失败: " + e.getMessage());
            requestLogService.saveRequestLog(log);

            return ResponseResult.fail("数据接收失败: " + e.getMessage());
        }
    }

    /*
     * 位置信息数据
     */
    @RequestMapping("/akq/locationData")
    public ResponseResult<Void> uploadLocationData(@RequestBody String requestBody, HttpServletRequest request) {
        RequestLogEntity log = new RequestLogEntity();
        try {
            // 校验请求参数
            if (!validateRequestBody(requestBody, LocationDataEntity.class)) {
                String errorMessage = "请求参数包含非法字段: " + requestBody;
                log.setNotes(errorMessage);
                log.setRequestUrl("/api/akq/locationData");
                log.setRequestMethod("POST");
                log.setRequestBody(requestBody);
                log.setRequestTime(LocalDateTime.now());
                log.setSuccess(false);
                log.setIp(IPUtils.getClientIp(request));
                requestLogService.saveRequestLog(log); // 保存日志
                return ResponseResult.fail(errorMessage);
            }

            LocationDataEntity data = objectMapper.readValue(requestBody, LocationDataEntity.class);

            // 记录请求前的信息
            log.setRequestUrl("/api/akq/locationData");
            log.setRequestMethod("POST");
            log.setRequestBody(requestBody);
            log.setRequestTime(LocalDateTime.now());
            log.setIp(IPUtils.getClientIp(request));

            dataService.saveLocationData(data);

            // 只有请求成功时才设置成功状态并保存日志
            log.setSuccess(true);
            requestLogService.saveRequestLog(log);

            return ResponseResult.success();
        } catch (Exception e) {
            // 记录请求失败信息
            log.setSuccess(false);
            log.setNotes("数据接收失败: " + e.getMessage());
            requestLogService.saveRequestLog(log);

            return ResponseResult.fail("数据接收失败: " + e.getMessage());
        }
    }

    /*
     * 告警数据
     */
    @RequestMapping("/akq/alarmData")
    public ResponseResult<Void> alarmData(@RequestBody String requestBody, HttpServletRequest request) {
        RequestLogEntity log = new RequestLogEntity();
        try {
            // 校验请求参数
            if (!validateRequestBody(requestBody, AlarmDataEntity.class)) {
                String errorMessage = "请求参数包含非法字段: " + requestBody;
                log.setNotes(errorMessage);
                log.setRequestUrl("/api/akq/alarmData");
                log.setRequestMethod("POST");
                log.setRequestBody(requestBody);
                log.setRequestTime(LocalDateTime.now());
                log.setSuccess(false);
                log.setIp(IPUtils.getClientIp(request));
                requestLogService.saveRequestLog(log); // 保存日志
                return ResponseResult.fail(errorMessage);
            }

            AlarmDataEntity data = objectMapper.readValue(requestBody, AlarmDataEntity.class);

            // 记录请求前的信息
            log.setRequestUrl("/api/akq/alarmData");
            log.setRequestMethod("POST");
            log.setRequestBody(requestBody);
            log.setRequestTime(LocalDateTime.now());
            log.setIp(IPUtils.getClientIp(request));

            dataService.saveAlarmData(data);

            // 只有请求成功时才设置成功状态并保存日志
            log.setSuccess(true);
            requestLogService.saveRequestLog(log);

            return ResponseResult.success();
        } catch (Exception e) {
            // 记录请求失败信息
            log.setSuccess(false);
            log.setNotes("数据接收失败: " + e.getMessage());
            requestLogService.saveRequestLog(log);

            return ResponseResult.fail("数据接收失败: " + e.getMessage());
        }
    }

    /**
     * 校验请求体是否包含非法字段
     * @param requestBody 请求体字符串
     * @param entityClass 实体类类型
     * @return 校验结果
     * @throws Exception 异常
     */
    private boolean validateRequestBody(String requestBody, Class<?> entityClass) throws Exception {
        ObjectNode jsonNode = objectMapper.readTree(requestBody).deepCopy();
        Set<String> fieldNames = getFieldNames(entityClass);
        for (Iterator<String> it = jsonNode.fieldNames(); it.hasNext(); ) {
            String field = it.next();
            if (!fieldNames.contains(field)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取实体类的所有字段名
     * @param entityClass 实体类类型
     * @return 字段名集合
     */
    private Set<String> getFieldNames(Class<?> entityClass) {
        Set<String> fieldNames = new HashSet<>();
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            fieldNames.add(field.getName());
        }
        return fieldNames;
    }
}